/*
 * Copyright (c) 2007 T.Cogghe, D.Leroux, S.Lévignac, S.Rives
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "Superpaws.hh"
#include "Matrice.hh"
#include "ImageRecadree.hh"
#include "Forme.hh"
#include "IHM/editAstres.hh"
#include <map>

Superpaws::Superpaws(int& argc,char**&argv) : IHM(argc,argv)
{}


Forme* retrouverForme(const Forme*aiguille, multimap<double,Astre*> meuleDeFoin[3]) {
	double dmin,delta;
	int n_comp;
	multimap<double,Astre*>::iterator ia,ja,ib,jb,ic,jc;
	Forme*fmin=NULL;

	ia=meuleDeFoin[0].begin();
	ja=meuleDeFoin[0].end();
	jb=meuleDeFoin[1].end();
	jc=meuleDeFoin[2].end();

	dmin=1000.;	/* un truc arbitrairement grand */
	n_comp=0;
	while(ia!=ja) {
		ib=meuleDeFoin[1].begin();
		while(ib!=jb) {
			ic=meuleDeFoin[2].begin();
			while(ic!=jc) {
				++n_comp;
				try
				{
					//	// allocation locale, plus rapide et légère
					Forme f((*ia).second,(*ib).second,(*ic).second);
					delta = f.id() % aiguille->id();

					if(delta < dmin) {
						if(fmin) {
							delete fmin;
						}
						//	// si la forme est temporairement validée, on la met sur le tas
						if(delta<Forme::Identite::_tol) {
							//return new Forme((*ia).second,(*ib).second,(*ic).second);
							return new Forme(f);
						}
						//fmin = new Forme((*ia).second,(*ib).second,(*ic).second);
						fmin = new Forme(f);
						dmin=delta;
					}

				}
				catch(FormeException&e)
				{
					//cerr<<"exception forme : "<<e.quoi()<<endl;
				}
				++ic;
			}
			++ib;
		}
		++ia;
	}
	
		
//	cout<<" après "<<n_comp<<" comparaisons, on a trouvé une forme proche à "<<(dmin*100.)<<"% de la forme de base"<<endl;

	return fmin;

}


double Superpaws::adv(const int i,const int n) const {
	return .5*((double)i)/(n*(nbImages()));
}

int Superpaws::traitement() {
	char buffer[256];
	std::string str;
	interrompu=0;
	multimap<double,Astre*> a[3];

	Matrice F1 = Matrice(	*image(0)->forme()->ast(0),
				*image(0)->forme()->ast(1),
				*image(0)->forme()->ast(2)).inverse();
	Matrice F2;

	if(!formesDetectees) {
		majProgression(str="Recherche des astres sur les images suivantes...\n",0);
		for(unsigned int i=1;i<nbImages()&&!interrompu;i++) {

			sprintf(buffer," * Image %i/%i :",i,nbImages());

			majProgression(str=buffer,.001+adv(3*i,3));

			for(int k=0;k<3;k++) {
				Astre::trouverDansRectangle(*image(i),image(0)->forme()->ast(k),0,0,image(i)->largeur(),image(i)->hauteur(),edAs->k(),a[k]);
//				cout<<" ° a["<<k<<"].size()="<<a[k].size()<<" et le plus proche astre est à "<<(*a[k].begin()).first<<endl;
			}
			sprintf(buffer," %i,%i,%i candidats\n",(int)a[0].size(),(int)a[1].size(),(int)a[2].size());

			majProgression(str=buffer,adv(3*i+1,3));

			image(i)->forme() = retrouverForme( image(0)->forme(), a );

			if(!(image(i)->forme()->id() == image(0)->forme()->id() )) {
				sprintf(buffer," attention, forme imparfaite (erreur : %lf %%)\n", (image(i)->forme()->id() % image(0)->forme()->id()) * 100. );
				majProgression(str=buffer,adv(3*i+1,3));
			}

			F2 = Matrice(	*image(i)->forme()->ast(0),
					*image(i)->forme()->ast(1),
					*image(i)->forme()->ast(2));
			/* on recadre */
			dynamic_cast<ImageRecadree*>(image(i))->matrice()= F2*F1;

			majProgression(str="   fini.\n",adv(3*i+2,3));
		//	image(i)->forme()->dump();
		}
		formesDetectees=true;
	}

	majProgression(str="== Superposition des images ==\n",.5);

	/* do some work */
	for(unsigned int i=1;i<nbImages()&&!interrompu;i++) {
		sprintf(buffer," * Image %i/%i\n   - calcul de la matrice\n",i,nbImages());
		majProgression(str=buffer,.5+adv(3*i,3));
		/* on superpose */
		majProgression(str="   - superposition\n",.5+adv(3*i+1,3));
		*iFin += *image(i);
		majProgression(str="   - fini.\n",.5+adv(3*i+2,3));
	}
	if(!interrompu) {
		traitementFini();
	}
	return 0;
}

void Superpaws::traitementAnnule() {
	interrompu=1;
	cout<<"traitement annulé !"<<endl;
}

Superpaws::~Superpaws() {
}





int main(int argc,char**argv) {
	{
		Superpaws supsup(argc,argv);
		supsup.run();
	}
	return 0;
}


